package nickthissen.iracing.activities;

import java.util.ArrayList;

import nickthissen.iracing.adapters.PagerAdapter;
import nickthissen.iracing.common.Cache;
import nickthissen.iracing.common.DataLoader;
import nickthissen.iracing.common.Error;
import nickthissen.iracing.common.ForumListManager;
import nickthissen.iracing.common.Prefs;
import nickthissen.iracing.common.ServiceLogging;
import nickthissen.iracing.common.Sharing;
import nickthissen.iracing.common.Task;
import nickthissen.iracing.datamodels.FavoriteThread;
import nickthissen.iracing.datamodels.Forum;
import nickthissen.iracing.datamodels.Page;
import nickthissen.iracing.datamodels.Result;
import nickthissen.iracing.datamodels.Thread;
import nickthissen.iracing.datamodels.ThreadList;
import nickthissen.iracing.adapters.ThreadListAdapter;
import nickthissen.iracing.datamodels.User;
import nickthissen.iracing.iracingforum2.R;
import nickthissen.iracing.networking.Networking;
import nickthissen.iracing.parsing.Parser;
import nickthissen.iracing.parsing.ThreadListParser;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.actionbarsherlock.internal.widget.IcsAdapterView;
import com.actionbarsherlock.internal.widget.IcsSpinner;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

public class ThreadListActivity extends TaskItemListActivity<Thread>
{
	private static final String FORUM_ID = "FORUM_ID";
    private static final String URL = "URL";
    private static final int NEWTHREAD = 1;

    private ArrayList<Page> pages;
    private IcsSpinner pageSpinner;

	private ThreadList threadList;
	private ProgressDialog dialog;	
	//private TextView lblPage;
	private ImageButton btnPrevPage, btnNextPage;
    private LinearLayout pageLayout;
	
	private String currentUrl, storedUrl;

	private int forumId;
	private Forum forum;
	
	@Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.threadlist);

        getSupportActionBar().setDisplayShowHomeEnabled(false);

        // Build UI
        //lblPage = (TextView) this.findViewById(R.id.lblPage);
        pageSpinner = (IcsSpinner) this.findViewById(R.id.pageSpinner);

        btnPrevPage = (ImageButton) this.findViewById(R.id.btnPrevPage);
        btnNextPage = (ImageButton) this.findViewById(R.id.btnNextPage);
        pageLayout = (LinearLayout) this.findViewById(R.id.pageLayout);

        btnPrevPage.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				previousPage();
			}
		});

        btnNextPage.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				nextPage();
			}
		});
        
        // Get forum
        Bundle extras = savedInstanceState;
        if (extras == null)
        {
            Intent i = this.getIntent();
            extras = i.getExtras();
        }
        forumId = extras.getInt(FORUM_ID);
        forum = ForumListManager.getInstance().forums.get(forumId);        
        if (forum == null) return;
        
        // Set current URL and title
        currentUrl = forum.Url;

        SherlockUtils.setMultilineTitle(this, forum.Title);
        
        this.loadData();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getSupportMenuInflater().inflate(R.menu.threadlist, menu);
        this.prepareWatchMenuItem(menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId()) {
            case R.id.mnuPost:
                this.newThread();
                return true;
            case R.id.mnuRefresh:
                Cache.removeForum(currentUrl);
                this.loadData();
                return true;
            case R.id.mnuShare:
                Sharing.shareForumUrl(this, currentUrl);
                return true;
            case R.id.mnuWatch:
                this.watch();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu)
    {
        this.prepareWatchMenuItem(menu);
        return super.onPrepareOptionsMenu(menu);
    }

    private void prepareWatchMenuItem(Menu menu)
    {
        MenuItem item = menu.findItem(R.id.mnuWatch);
        if (item != null)
        {
            if (forum != null)
            {
                if (forum.IsWatching)
                    item.setTitle(R.string.unwatch);
                else
                    item.setTitle(R.string.watchforum);
            }
        }
    }

    @Override
    protected Task<String> createTask()
    {
        return new Task<String>(this, loader);
    }

    @Override
    protected void saveTaskInput(Bundle state)
    {
        state.putString(URL, storedUrl);
    }

    @Override
    public Object restoreTaskInput(Bundle state)
    {
        return state.getString(URL);
    }

	@Override
	public void onSaveInstanceState(Bundle outState)
	{
		outState.putInt(FORUM_ID, forum.Id);
		super.onSaveInstanceState(outState);
	}

	@Override
	public void onRestoreInstanceState(Bundle state)
	{
        int id = state.getInt(FORUM_ID);
        forum = ForumListManager.getInstance().forums.get(id);
        
		super.onRestoreInstanceState(state);
	}
	
	public static Intent getIntent(Context context, int forumId)
	{
		Intent i = new Intent(context, ThreadListActivity.class);
		i.putExtra(FORUM_ID, forumId);
		return i;
	}
	
	@Override
	protected void loadData()
	{
        boolean allowCache = Prefs.get(this).getBoolean(R.string.PREF_ThreadCaching, true);

        boolean shouldLoadInBackground = false;
        if (allowCache)
        {
            ThreadList cached = Cache.loadForum(currentUrl);
            if (cached != null)
            {
                threadList = cached;
                isInitialized = false;
                setItems(cached.Threads);

                shouldLoadInBackground = true;
            }
            else
            {
                shouldLoadInBackground = false;
            }
        }

        this.loadThreadList(currentUrl, shouldLoadInBackground);
	}

	private void loadThreadList(String url, boolean background)
	{
        storedUrl = url;
		this.startLoading("Loading threads...", url, background);

        ServiceLogging.logPageRequest(this, url);
	}
	
	@Override
	protected void setItems(ArrayList<Thread> items) 
	{
		for (Thread t : items)
		{
			t.ForumId = forum.Id;
		}
		
		ThreadListAdapter adapter;
        if (this.getListAdapter() == null)
        {
            adapter = new ThreadListAdapter(this, R.layout.threadrow, items);
            this.setListAdapter(adapter);
        }
        else
        {
            adapter = (ThreadListAdapter) this.getListAdapter();
            adapter.clear();
            for (Thread t : items)
            {
                adapter.add(t);
            }
        }

        setPagination();
	}

	@Override
	public void onItemClicked(Thread item) 
	{
        this.onItemClicked(item, false);
	}
	
	public void onItemClicked(Thread item, boolean latestReply) 
	{
		this.openThread(item, latestReply);
	}

    public boolean addFavorite(Thread item)
    {
        DialogClickListener clickListener = new DialogClickListener(this, item);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Do you want to add this thread to your favorites?")
                .setPositiveButton("Yes", clickListener)
                .setNegativeButton("No", clickListener)
                .show();
        return true;
    }

    private class DialogClickListener implements DialogInterface.OnClickListener
    {
        Activity context;
        Thread thread;
        FavoriteThread favorite;

        public DialogClickListener(Activity context, Thread thread)
        {
            this.context = context;
            this.thread = thread;
            this.favorite = FavoriteThread.fromThread(thread, User.currentUser.username);
        }

        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            if (which == DialogInterface.BUTTON_POSITIVE)
            {
                new Task<FavoriteThread>(context, new DataLoader<FavoriteThread>()
                {
                    @Override
                    public Result getData(FavoriteThread in)
                    {
                        return Networking.addFavorite(this.getContext(), User.currentUser, in);
                    }

                    @Override
                    public void onFinished(Result out)
                    {
                        if (out.Success)
                        {
                            Toast.makeText(context, "Favorite saved.", Toast.LENGTH_SHORT).show();
                        }
                        else
                        {
                            Error.fromResult(out).report(this.getContext());
                        }
                    }
                }).execute(favorite);
            }
            dialog.dismiss();
        }
    }

    private boolean isInitialized = false;

    private void setPagination()
    {
        if (threadList == null) return;

        isInitialized = false;
        pages = Page.fromList(threadList);

        if (!threadList.HasPagination)
        {
            pageLayout.setVisibility(View.GONE);
        }
        else
        {
            pageLayout.setVisibility(View.VISIBLE);

            pageSpinner.setAdapter(new PagerAdapter(this, 0, pages));
            pageSpinner.setSelection(threadList.Page - 1);

            pageSpinner.setOnItemSelectedListener(new IcsAdapterView.OnItemSelectedListener()
            {
                @Override
                public void onItemSelected(IcsAdapterView<?> parent, View view, int position, long id)
                {
                    if (!isInitialized)
                    {
                        isInitialized = true;
                        return;
                    }

                    if (position >= 0 && position < pages.size())
                    {
                        Page page = pages.get(position);
                        String url = page.getForumUrl(currentUrl);
                        changePage(url);
                    }
                }

                @Override
                public void onNothingSelected(IcsAdapterView<?> parent)
                {
                }
            });

            btnPrevPage.setEnabled(threadList.Page > 1);
            btnNextPage.setEnabled(threadList.Page < threadList.LastPage);
        }
    }

    private void changePage(String url)
    {
        isInitialized = false;
        currentUrl = url;
        threadList = null;
        this.loadData();
    }

	private void previousPage()
	{
        if (threadList == null) return;
        this.changePage(threadList.PreviousPageUrl);
	}
	
	private void nextPage()
	{
        if (threadList == null) return;
        this.changePage(threadList.NextPageUrl);
	}

    private void openThread(Thread thread, boolean latestReply)
    {
        Intent i = ThreadActivity.getIntent(this, thread, forum.Id, latestReply);
        this.startActivityForResult(i, 0);
    }

    private void newThread()
    {
        if (forum == null || threadList == null) return;
        if (!threadList.CanPost)
        {
            Toast.makeText(this, "You cannot create a thread in this forum.", Toast.LENGTH_SHORT).show();
            return;
        }

        Intent intent = PostThreadActivity.getPostIntent(this, forum.Id);
        this.startActivityForResult(intent, NEWTHREAD);
    }

    private void watch()
    {
        new Task<Forum>(this, new DataLoader<Forum>()
        {
            @Override
            public Result getData(Forum in)
            {
                Networking.toggleWatchForum(this.getContext(), in);
                return Result.ok(in.IsWatching);
            }

            @Override
            public void onFinished(Result out)
            {
                String msg;
                if ((Boolean)out.Object)
                    msg = "You are now watching this forum.";
                else
                    msg = "You are no longer watching this forum.";
                Toast.makeText(this.getContext(), msg, Toast.LENGTH_LONG).show();
            }
        }).execute(forum);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode == RESULT_OK && requestCode == NEWTHREAD)
        {
            this.loadData();
        }
    }

	private DataLoader<String> loader = new DataLoader<String>() 
			{
				@Override
				public Result getData(String in) 
				{
					// Obtain thread list page source
					Result result = Networking.getThreadList(this.getContext(), in);
					
					if (result.Success) 
					{
						// Parse source and return threadlist result
						String source = (String)result.Object;				
						Parser parser = new ThreadListParser();
						return parser.parse(source);
					}
					else
					{
						// Error
						return result;
					}
				}

				@Override
				public void onFinished(Result out) 
				{
					if (out.Success)
					{
						threadList = (ThreadList)out.Object;
					}
					else
					{
						// Error						
						threadList = new ThreadList();
						threadList.Threads = new ArrayList<Thread>();
						
						Error.fromResult(out).report(this.getContext());
					}

                    forum.IsWatching = threadList.IsWatching;

					setItems(threadList.Threads);
                    Cache.saveForum(threadList, currentUrl);
					finishedLoading();
				}				
			};
}
